package westh.ilib.service.surveyReport.documentSearch;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONObject;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

import westh.ilib.bean.croDomainSearch.Resource;

/**
 * transform xml file or Resource into Document for index
 * @author Zhang Yanxing
 * 2010-8-19
 */

/** A utility for making Lucene Documents from a xml File. */

public class FileDocument {
	/**
	 * Makes a document for a File.
	 * <p>
	 * The document has these fields:
	 * <ul>
	 * <li><code>path</code>--containing the pathname of the file, as a stored,
	 * untokenized field;
	 * <li><code>year</code>--containing the published year of the file, as a
	 * stored, untokenized field;
	 * <li><code>conf</code>--containing the conference that the file published,
	 * as a stored, untokenized field;
	 * <li><code>title</code>--containing the title of the file, as a stored,
	 * tokenized field;
	 * <li><code>keyword</code>--containing the keyword of the file, as a
	 * stored, tokenized field;
	 * <li><code>summary</code>--containing the 'abstract' of the file, as a
	 * stored, tokenized field;
	 * <li><code>contents</code>--containing the full contents of the file, as a
	 * stored, tokenized field;
	 * <li><code>rscType</code>--containing the rscType of the file, as a
	 * stored, tokenized field;
	 */
	public static Document Document(File f)
			throws java.io.FileNotFoundException {
		// make a new, empty document
		Document doc = new Document();

		// Add the path of the file as a field named "path". Use a field that is
		// indexed (i.e. searchable), but don't tokenize the field into words.
		doc.add(new Field("path", f.getPath(), Field.Store.YES,
				Field.Index.NOT_ANALYZED));

		// Add fields of year, conference, title of the file
		// parsing the year, conference, title from the file name
		String filename = f.getName();
		String year = filename.substring(0, 4);

		int pos1, pos2;
		pos1 = filename.indexOf('-');
		pos2 = filename.indexOf('-', pos1 + 1);
		String conf = filename.substring(pos1 + 1, pos2);
		String title = filename.substring(pos2 + 1, filename.length() - 4);
		title = title.replace("_ ", ": ");

		doc.add(new Field("year", year, Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		doc.add(new Field("conf", conf, Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		doc
				.add(new Field("title", title, Field.Store.YES,
						Field.Index.ANALYZED));

		// Add fields of the keyword, abstract, full content of the file
		// first read in the file,
		// then parsing keyword, abstract, full content from xml file using
		// regular expression
		try {
			BufferedReader br = new BufferedReader(new FileReader(f));
			char[] cbuf = new char[(int) f.length()];
			while (br.ready()) {
				br.read(cbuf, 0, (int) f.length());
			}
			String str = new String(cbuf);

			// parsing and add field of keyword
			String keywordEx = "<keywords>(.+?)</keywords>";
			Pattern keywordPattern = Pattern.compile(keywordEx,
					Pattern.MULTILINE | Pattern.DOTALL);
			Matcher keywordMatcher = keywordPattern.matcher(str);
			String keyword = "";
			if (keywordMatcher.find()) {
				keyword = keywordMatcher.group(0);
				keyword = keyword.substring(10, keyword.length() - 11);
				if (keyword.equalsIgnoreCase("null")) {
					keyword = "";
				}
			}
			doc.add(new Field("keyword", keyword, Field.Store.YES,
					Field.Index.ANALYZED));

			// parsing and add field of abstract
			String abstractEx = "<abstract>(.+?)</abstract>";
			Pattern abstractPattern = Pattern.compile(abstractEx,
					Pattern.MULTILINE | Pattern.DOTALL);
			Matcher abstractMatcher = abstractPattern.matcher(str);
			String summary = "";
			if (abstractMatcher.find()) {
				summary = abstractMatcher.group(0);
				summary = summary.substring(10, summary.length() - 11);
				if (summary.length() > 8
						&& summary.substring(0, 8).compareToIgnoreCase(
								"abstract") == 0) {
					summary = summary.substring(8).trim();
				}
			}
			doc.add(new Field("summary", summary, Field.Store.YES,
					Field.Index.ANALYZED));

			// parsing and add field of full content
			String bodyEx = "<body>(.+?)</body>";
			Pattern bodyPattern = Pattern.compile(bodyEx, Pattern.MULTILINE
					| Pattern.DOTALL);
			Matcher bodyMatcher = bodyPattern.matcher(str);
			String body = "";
			if (bodyMatcher.find()) {
				body = bodyMatcher.group(0);
				body = body.substring(6, body.length() - 7);
			}
			doc.add(new Field("contents", body, Field.Store.YES,
					Field.Index.ANALYZED));

			doc.add(new Field("rscType", "2", Field.Store.YES,
					Field.Index.NOT_ANALYZED));
		} catch (Exception e) {
			e.printStackTrace();
		}

		// set different boosts for each fields
		doc.getField("title").setBoost((float) 1.0);
		doc.getField("keyword").setBoost((float) 0.8);
		doc.getField("summary").setBoost((float) 0.6);
		doc.getField("contents").setBoost((float) 0.5);
		// return the document
		return doc;
	}

	/**
	 * Makes a document for a Resource.
	 * <p>
	 * The document has these fields:
	 * <ul>
	 * <li><code>path</code>--containing the pathname of the Resource, as a
	 * stored, untokenized field;
	 * <li><code>year</code>--containing the published year of the Resource, as
	 * a stored, untokenized field;
	 * <li><code>conf</code>--containing the conference that the Resource
	 * published, as a stored, untokenized field;
	 * <li><code>title</code>--containing the title of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>keyword</code>--containing the keyword of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>summary</code>--containing the 'abstract' of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>contents</code>--containing the full contents of the Resource,
	 * as a stored, tokenized field;
	 * <li><code>rscType</code>--containing the rscType of the Resource, as a
	 * stored, tokenized field;
	 */
	public static Document Document(Object obj)
			throws java.io.FileNotFoundException {
		JSONObject object = (JSONObject)obj;
		
		// make a new, empty document
		Document doc = new Document();

		// Add the rscId of Resource as a field named "path". Use a field that
		// is
		// indexed (i.e. searchable), but don't tokenize the field into words.
		doc.add(new Field("path", object.getString("rscId"), Field.Store.YES,
				Field.Index.NOT_ANALYZED));

		String rscSource = object.getString("rscSource");
		
		String yearPatternStr = "dddd";
		Pattern yearPattern = Pattern.compile(yearPatternStr);
		Matcher matcher = yearPattern.matcher(rscSource);
		
		doc.add(new Field("conf", rscSource, Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		
		if(matcher.groupCount() > 0){
		doc.add(new Field("year", matcher.group(0), Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		}
		
		doc.add(new Field("title", object.getString("rscTitle"), Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("keyword", object.getString("rscSubject"), Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("summary", object.getString("rscAbstract"), Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("contents", "", Field.Store.YES,
						Field.Index.ANALYZED));
		
		doc.add(new Field("rscType", object.getString("rscType"), Field.Store.YES, Field.Index.NOT_ANALYZED));
		if(doc.getField("rscType").stringValue().isEmpty()){
			doc.getField("rscType").setValue("2");
		}

		// set different boosts for each fields
		doc.getField("title").setBoost((float) 1.0);
		doc.getField("keyword").setBoost((float) 0.8);
		doc.getField("summary").setBoost((float) 0.6);
		doc.getField("contents").setBoost((float) 0.5);
		
		// return the document
		return doc;
	}

	/**
	 * Makes a document for a Resource.
	 * <p>
	 * The document has these fields:
	 * <ul>
	 * <li><code>path</code>--containing the pathname of the Resource, as a
	 * stored, untokenized field;
	 * <li><code>year</code>--containing the published year of the Resource, as
	 * a stored, untokenized field;
	 * <li><code>conf</code>--containing the conference that the Resource
	 * published, as a stored, untokenized field;
	 * <li><code>title</code>--containing the title of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>keyword</code>--containing the keyword of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>summary</code>--containing the 'abstract' of the Resource, as a
	 * stored, tokenized field;
	 * <li><code>contents</code>--containing the full contents of the Resource,
	 * as a stored, tokenized field;
	 * <li><code>rscType</code>--containing the rscType of the Resource, as a
	 * stored, tokenized field;
	 */
	public static Document Document(Resource rsc)
			throws java.io.FileNotFoundException {
		// make a new, empty document
		Document doc = new Document();

		// Add the rscId of Resource as a field named "path". Use a field that
		// is
		// indexed (i.e. searchable), but don't tokenize the field into words.
		doc.add(new Field("path", rsc.getRscId(), Field.Store.YES,
				Field.Index.NOT_ANALYZED));

		doc.add(new Field("year", rsc.getRscPublishDate(), Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		doc.add(new Field("conf", rsc.getRscPublisher(), Field.Store.YES,
				Field.Index.NOT_ANALYZED));
		doc.add(new Field("title", rsc.getRscTitle(), Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("keyword", rsc.getRscSubject(), Field.Store.YES,
				Field.Index.ANALYZED));

		doc.add(new Field("summary", rsc.getRscAbstract(), Field.Store.YES,
				Field.Index.ANALYZED));

		doc
				.add(new Field("contents", "", Field.Store.YES,
						Field.Index.ANALYZED));

		if (rsc.getRscType() != 0) {
			doc.add(new Field("rscType", Integer.toString(rsc.getRscType()),
					Field.Store.YES, Field.Index.NOT_ANALYZED));
		} else {
			doc.add(new Field("rscType", "2", Field.Store.YES,
					Field.Index.NOT_ANALYZED));
		}

		// set different boosts for each fields
		doc.getField("title").setBoost((float) 1.0);
		doc.getField("keyword").setBoost((float) 0.8);
		doc.getField("summary").setBoost((float) 0.6);
		doc.getField("contents").setBoost((float) 0.5);

		// return the document
		return doc;
	}

	private FileDocument() {
	}

	public static void main(String[] args) {
		// unit test
		try {
			Document doc = FileDocument
					.Document(new File(
							"E:\\zhyx\\SurveyReport\\xml\\2000-CIKM-A comparison of DFT and DWT based similarity search in time-series databases.xml"));
			System.out.println(doc.getField("path"));
			System.out.println(doc.getField("year"));
			System.out.println(doc.getField("conf"));
			System.out.println(doc.getField("title"));
			System.out.println(doc.getField("keyword"));
			System.out.println(doc.getField("summary"));
			System.out.println(doc.getField("contents"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
